﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Battles.Atomics;

namespace Battles.Controls
{
	public partial class ArmyPlacement : UserControl
	{
		protected const string EMPTY_SLOT_STRING = "- Empty -";
		protected const int ROW_SIZE = 7;
		protected List<Warrior> army;
		protected List<ComboBox> row1;
		protected List<ComboBox> row2;

		#region - Properties. -
		public List<Warrior> Army
		{
			get { return army; }
			set
			{
				army = value;

				// Fill combo-boxes.
				//vacantNames = Utils.GetAllNames(army);
				var vacantNames = new List<string>(army.Count + 1);
				vacantNames.Add(EMPTY_SLOT_STRING);
				foreach (var warrior in army)
				{
					vacantNames.Add( GetNameListEntry(warrior) );
				}
				FillCombos(row1, vacantNames);
				FillCombos(row2, vacantNames);

				foreach (var box in row1) { box.SelectedIndex = 0; }
				foreach (var box in row2) { box.SelectedIndex = 0; }
			}
		}

		public Atomics.ArmyPlacement Placement
		{
			get
			{
				var res = new Atomics.ArmyPlacement(ROW_SIZE);

				for (int i = 0; i < row1.Count; i++)
				{
					var box = row1[i];
					if (box.SelectedIndex <= 0) continue;	// if no warrior is selected.

					var name = box.SelectedItem.ToString().Trim();
					if (name.Length > 0)
					{
						res.Row1[i] = Utils.GetWarriorByName(army, name);
					}
				}

				for (int i = 0; i < row2.Count; i++)
				{
					var box = row2[i];
					if (box.SelectedIndex <= 0) continue;	// if no warrior is selected.

					var name = box.SelectedItem.ToString().Trim();
					if (name.Length > 0)
					{
						res.Row2[i] = Utils.GetWarriorByName(army, name);
					}
				}

				return res;
			}
		}
		#endregion

		#region - Construction and initialization. -
		public ArmyPlacement()
		{
			InitializeComponent();

			// prepare temporal containers.
			row1 = new List<ComboBox>(ROW_SIZE);
			row1.Add(Place11Combo);
			row1.Add(Place12Combo);
			row1.Add(Place13Combo);
			row1.Add(Place14Combo);
			row1.Add(Place15Combo);
			row1.Add(Place16Combo);
			row1.Add(Place17Combo);
			foreach (var box in row1) { box.SelectionChangeCommitted += SoldierSelected; }

			row2 = new List<ComboBox>(ROW_SIZE);
			row2.Add(Place21Combo);
			row2.Add(Place22Combo);
			row2.Add(Place23Combo);
			row2.Add(Place24Combo);
			row2.Add(Place25Combo);
			row2.Add(Place26Combo);
			row2.Add(Place27Combo);
			foreach (var box in row2) { box.SelectionChangeCommitted += SoldierSelected; }
		}

		public void FillCombos(List<ComboBox> row, List<string> names)
		{
			var objNames = new object[names.Count];
			for (int i = 0; i < names.Count; i++)
			{
				var s = names[i];
				objNames[i] = s;
			}

			foreach (var box in row)
			{
				box.Items.Clear();
				box.Items.AddRange(objNames);
			}
		} 
		#endregion

		/// <summary>
		/// Adds given name to all boxes in a collection.
		/// </summary>
		/// <param name="row"></param>
		/// <param name="name"></param>
		public void AddName(List<ComboBox> row, string name)
		{
			foreach (var box in row)
			{
				box.Items.Add(name);
			}
		}

		/// <summary>
		/// Removes given name from all boxes in a collection.
		/// </summary>
		/// <param name="row"></param>
		/// <param name="name"></param>
		public void RemoveName(List<ComboBox> row, string name)
		{
			foreach (var box in row)
			{
				box.Items.Remove(name);
			}
		}

		public string GetNameListEntry (Warrior w)
		{
			var format = "[{0}] {1}";
			var type = w.Type.ToString()[0];
			return string.Format(format, type, w.Name);
		}

		/// <summary>
		/// Extracts name from a given list-box entry.
		/// </summary>
		/// <param name="name"></param>
		/// <returns></returns>
		public string ExtractName (string name)
		{
			var idx = name.LastIndexOf(']');
			return name.Substring(idx + 2);
		}

		#region - Event handlers. -
		public void SoldierSelected (object obj, EventArgs args)
		{
			var temp = (ComboBox) obj;

			// 0. check tag. If not zero then get back the vacant coldier name
			if (temp.Tag != null)
			{
				var w = (Warrior)temp.Tag;
				var wname = GetNameListEntry(w);
				AddName(row1, wname);
				AddName(row2, wname);
				temp.Items.Remove(wname);
			}

			if (temp.SelectedItem.ToString() == EMPTY_SLOT_STRING)
			{
				temp.Tag = null;
				return;
			}

			// 1. find soldier with currently selected name.
			var name = ExtractName (temp.SelectedItem.ToString());
			var warrior = Utils.GetWarriorByName(army, name);
			name = GetNameListEntry(warrior);
			RemoveName(row1, name);
			RemoveName(row2, name);
			temp.Items.Add(name);
			temp.SelectedItem = name;
			
			// 2. set this new soldier to the tag.
			temp.Tag = warrior;
		}
		#endregion
	}
}
